# cronmon - Cron e-mail filtering and management
# Copyright (c) 2010 Crown copyright
# 
# This file is part of cronmon.
# 
# cronmon is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# cronmon is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with cronmon.  If not, see <http://www.gnu.org/licenses/>.

import re
import datetime

from django.db import models
from django.conf import settings
import urlparse

from email.parser import FeedParser


IMPORTANCE = [
    (1, 'Notice'),
    (2, 'Warning'),
    (3, 'Critical'),
]

STATUS = [
    ('-', 'New'),
    ('E', 'Escalated'),
    ('I', 'Ignored'),
]

class Tag(models.Model):
    name = models.SlugField(max_length=64, unique=True)

    def __unicode__(self):
        return self.name

    def new_issues(self):
        return self.message_set.filter(status='-')

    @models.permalink
    def get_absolute_url(self):
        return 'cron-by-tag', (), {'tag': self.name}


class Host(models.Model):
    name = models.CharField(max_length=255, unique=True, db_index=True)

    def __unicode__(self):
        return self.name

    def new_issues(self):
        return self.message_set.filter(status='-')

    @models.permalink
    def get_absolute_url(self):
        return 'cron-by-host', (), {'hostname': self.name}


class MessageManager(models.Manager):
    def new(self):
        return self.filter(status='-')

    def critical(self):
        return self.new().filter(importance=3)

    def warning(self):
        return self.new().filter(importance__gte=2)

    def expression(self, expr):
        from cronmon.tagging.tag_query import tag_query
        return tag_query(expr)

    def today(self):
        return self.new().filter(received__gte=datetime.date.today())

    def get_query_set(self):
        return super(MessageManager, self).get_query_set().defer('message')


class Message(models.Model):
    received = models.DateTimeField(auto_now_add=True)
    host = models.ForeignKey(Host)
    importance = models.IntegerField(choices=IMPORTANCE, default=3)

    status = models.CharField(max_length=1, choices=STATUS, default='-')

    subject = models.CharField(max_length=255, blank=True)
    date = models.DateTimeField()
    sha1 = models.CharField(max_length=40, help_text="SHA1 hash of body", db_index=True)

    body = models.TextField() # first 1000 lines of message body
    message = models.TextField()

    ticket = models.IntegerField(blank=True, null=True)

    tags = models.ManyToManyField(Tag, blank=True)

    objects = MessageManager()

    def __unicode__(self):
        return '%s: %s' % (self.host, self.subject)

    def as_message(self):
        try:
            return self._msg
        except AttributeError:
            fp = FeedParser()
            fp.feed(self.message.replace(u'\n', u'\r\n').encode('utf8'))
            self._msg = fp.close()
            return self._msg

#    def date(self):
#        d = self.as_message()['Date']
#        d = re.sub(r'^[A-Za-z]{3}, (.*) (\+\d{4}|GMT)$', r'\1', d)
#        return datetime.datetime.strptime(d, '%d %b %Y %H:%M:%S')

    def text_body(self):
        m = self.as_message()
        if m.is_multipart():
            for part in m.walk():
                if part.get_content_type() == 'text/plain':
                    break
            else:
                for part in m.walk():
                    if part.get_content_maintype() == 'text':
                        break
                else:
                    # Fall back to the first part
                    part = m.get_payload()[0]
            charset = part.get_content_charset() or 'ascii'
            return part.get_payload(decode=True).decode(charset)
        else:
            charset = m.get_content_charset() or 'ascii'
            try:
                return m.get_payload(decode=True).decode(charset)
            except UnicodeDecodeError:
                return m.get_payload(decode=True).decode('iso-8859-1')

    def get_rt_url(self):
        if not self.ticket:
            return None
        return urlparse.urljoin(settings.RT_BASE_URL, 'Ticket/Display.html') + '?id=%d' % self.ticket

    def discard(self, commit=True):
        self.status = 'I'
        if commit:
            self.save()

    def add_tag(self, name):
        t, created = Tag.objects.get_or_create(name=name)
        self.tags.add(t)

    def add_log_message(self, comment, type='info'):
        self.messagestatuslog_set.create(type=type, comment=comment)

    @models.permalink
    def get_absolute_url(self):
        return 'message', (), {'id': self.id}

    class Meta:
        ordering = '-date', '-importance' 


class MessageStatusLog(models.Model):
    date = models.DateTimeField(auto_now_add=True)
    message = models.ForeignKey(Message)
    type = models.CharField(max_length=32)

    comment = models.TextField()

    def __unicode__(self):
        return self.comment

    class Meta:
        ordering = 'date',
